package myClient.clientCore;

import component.timeConsumingTask.ExecuteTaskCollector;
import component.userInformation.UserAttribute;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.EventLoop;
import io.netty.util.concurrent.GenericFutureListener;
import lombok.Data;
import myClient.command.*;
import myClient.sender.ChatSender;
import myClient.sender.LoginSender;
import myClient.session.ClientSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;

@Data
@Service("CommandController")
public class CommandController {

    @Autowired
    ClientCommandMenu clientCommandMenu;  //菜单命令收集类  0
    @Autowired
    LoginConsoleCommand loginConsoleCommand;  //登录命令收集类  1
    @Autowired
    ChatConsoleCommand chatConsoleCommand;  //聊天命令收集类  2
    @Autowired
    LogoutConsoleCommand logoutConsoleCommand;  //退出命令收集类  3
    //监听 连接关闭状态
    GenericFutureListener<ChannelFuture> closeListener = (ChannelFutureListener) future -> {
        System.out.println(new Date() + ": 连接已断开。。。");
        //通过 Session关闭 Channel
        future.channel()
                .attr(ClientSession.SESSION_KEY)
                .get()
                .closeChannelBySession();
        //唤醒用户线程
        notifyCommandThread();
    };
    private Map<String, BaseCommand> commandMap;
    @Autowired
    private ChatNettyClient chatNettyClient;  //
    @Autowired
    private ChatSender chatSender;  //发送聊天信息
    @Autowired
    private LoginSender loginSender;  //发送登录信息
    private ClientSession session;  //会话类
    private UserAttribute user;    //用户信息
    private Channel channel;   // Channel
    private boolean connectFlag = false;  //连接是否成功
    //监听 连接建立状态
    GenericFutureListener<ChannelFuture> connectedListener = (ChannelFutureListener) future -> {
        final EventLoop eventLoop = future.channel().eventLoop();
        if (future.isSuccess()) {
            //连接建立成功
            connectFlag = true;
            System.out.println("成功连接服务器。。。");
            channel = future.channel();
            //创建 Session，并将 Channel绑定到 Session
            session = new ClientSession(channel);
            session.setConnected(true);
            channel.closeFuture().addListener(closeListener);
            //唤醒用户线程
            notifyCommandThread();
        } else {
            System.out.println("连接服务器失败！ 10秒后尝试重新连接。。。");
            eventLoop.schedule(() -> {
                chatNettyClient.connectServer();
            }, 10, TimeUnit.SECONDS);

            connectFlag = false;
        }
    };

    /**
     * wait
     */
    public synchronized void waitCommandThread() {
        //休眠，命令收集线程
        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * notify
     */
    public synchronized void notifyCommandThread() {
        //唤醒，命令收集线程
        this.notify();
    }

    /**
     * 初始化 commandMap ，将所有的控制命令 command输出到终端 terminal显示
     */
    public void initCommandMap() {
        commandMap = new HashMap<>();
        commandMap.put(clientCommandMenu.getKey(), clientCommandMenu);
        commandMap.put(chatConsoleCommand.getKey(), chatConsoleCommand);
        commandMap.put(loginConsoleCommand.getKey(), loginConsoleCommand);
        commandMap.put(logoutConsoleCommand.getKey(), logoutConsoleCommand);

        clientCommandMenu.setAllCommand(commandMap);
    }

    public void startConnectServer() {
        ExecuteTaskCollector.add(() ->
        {
            chatNettyClient.setConnectedListener(connectedListener);
            chatNettyClient.connectServer();
        });
    }

    public void commandThreadRunning() throws InterruptedException {
        Thread.currentThread().setName("命令线程");

        while (true) {
            //建立连接
            while (!connectFlag) {
                //开始连接
                startConnectServer();
                waitCommandThread();
            }
            //处理命令
            while (session != null) {
                Scanner scanner = new Scanner(System.in);
                clientCommandMenu.exec(scanner);
                String key = clientCommandMenu.getCommandInput();
                BaseCommand command = commandMap.get(key);

                if (command == null) {
                    System.err.println("无法识别[" + command + "]指令，请重新输入!");
                    continue;
                }
                switch (key) {
                    case LoginConsoleCommand.KEY:
                        command.exec(scanner);
                        startLogin((LoginConsoleCommand) command);
                        break;
                    case ChatConsoleCommand.KEY:
                        command.exec(scanner);
                        startSingleChat((ChatConsoleCommand) command);
                        break;
                    case LogoutConsoleCommand.KEY:
                        command.exec(scanner);
                        startLogout(command);
                        break;
                }
            }
        }
    }

    private void startLogin(LoginConsoleCommand command) {
        //登录
        if (!isConnectFlag()) {
            System.out.println("连接异常，请重新建立连接");
            return;
        }
        UserAttribute user = new UserAttribute();
        user.setUid(command.getUserName());
        user.setToken(command.getPassWord());
        user.setDeviceID("1");
        this.user = user;
        session.setUserAttribute(user);
        loginSender.setUserAttribute(user);
        loginSender.setSession(session);
        loginSender.sendLoginMsg();
    }

    //发送单聊消息
    private void startSingleChat(ChatConsoleCommand c) {
        //登录
        if (isNotLogin()) {
            System.out.println("还没有登录，请先登录");
            return;
        }
        chatSender.setSession(session);
        chatSender.setUserAttribute(user);
        chatSender.sendChatMsg(c.getToUserId(), c.getMessage());
    }

    private void startLogout(BaseCommand command) {
        //登出
        if (isNotLogin()) {
            System.out.println("还没有登录，请先登录");
        }
    }

    public boolean isNotLogin() {
        if (session == null) {
            System.out.println("session is null");
            return true;
        }
        return !session.isLogin();
    }

}
